﻿using System;

namespace RexToy.UI.Controls
{
    [NoCompile]
    class Delta
    {
        public int x = 0;
        public int y = 0;
    }

    public class ScrollBase : Container
    {
        private bool __allowVertical;
        public bool AllowVertical
        {
            get { return __allowVertical; }
            set { __allowVertical = value; }
        }

        private bool __allowHorizon;
        public bool AllowHorizon
        {
            get { return __allowHorizon; }
            set { __allowHorizon = value; }
        }

        private int _posX = 0;
        private int _posY = 0;
        private int _top = 0;
        private int _left = 0;

        private int viewHeight;
        private int dragHeight;
        private int viewWidth;
        private int dragWidth;
        private uint _start_msec;
        private uint _stop_msec;

        public ScrollBase()
        {
            this.__dragEnable = true;
            this.__dragEventBubble = false;
            this.__sizeUpdate = true;
            this.__allowVertical = true;
            this.__allowHorizon = false;

            this.__domNode = RexToy.UI.Controls.DomNode.Create(new DomNodeCreateOptions()
            {
                tag = Tag.Div,
                className = "ui-scroll-container ui-body-c",
                items = new DomNodeCreateOptions[]
            { 
                new DomNodeCreateOptions()
                {
                    tag = Tag.Div,
                    hashName = "container",
                    className = "ui-scroll"
                }
            }
            });
        }

        /*
    render: function (size) {
        this.$super(size);
    },*/

        public void ResetScroll()
        {
            var style = this.__domNode.SearchByName("container").GetStyle();
            if (this.__allowHorizon)
            {
                this._left = 0;
                style.MarginLeft = "0px";
            }
            if (this.__allowVertical)
            {
                this._top = 0;
                style.MarginTop = "0px";
            }
        }

        private void StartDrag()
        {
            this._start_msec = new DateTime().Time;
            var e = this.__domNode.SearchByName("container")._element;
            this.dragHeight = 0;
            this.dragWidth = 0;
            for (var i = 0; i < this.__controls.Length; i++)
            {
                this.dragHeight += this.__controls[i].GetSize().Height;
            }
            if (this.__controls.Length > 0)
            {
                this.dragWidth = this.__controls[0].GetSize().Width;
            }

            e = this.__domNode._element;
            this.viewWidth = (int)Math.Min(e.ScrollWidth, e.OffsetWidth, e.ClientWidth);
            this.viewHeight = (int)Math.Min(e.ScrollHeight, e.OffsetHeight, e.ClientHeight);
        }

        private void StopDrag(Delta delta)
        {
            this._stop_msec = new DateTime().Time;
            var t = this._stop_msec - this._start_msec;

            var style = this.__domNode.SearchByName("container").GetStyle();
            //Note:Inertia, calc speed, and assume a = 50px/s/s
            var vx = delta.x / t * 1000;
            var vy = delta.y / t * 1000;
            var a = 50;
            var ax = (vx > 0) ? -a : a;
            var ay = (vy > 0) ? -a : a;

            int sid = 0;
            uint interval = 25;
            var move_y = this.__allowVertical && (this.dragHeight > this.viewHeight);
            var move_x = this.__allowHorizon && (this.dragWidth > this.viewWidth);

            Action _m = delegate() {
                //Note:Vertical
                if (move_y) {
                    vy += ay;
                    if (Math.Abs(vy) <= a) {
                        move_y = false;
                        this._posY = this._top;
                    } else {
                        this._top += (int)(vy * interval / 1000);
                        style.MarginTop = this._top + "px";

                        if (vy < 0 && this.viewHeight - this._top > this.dragHeight) {
                            this._top = this._posY = this.viewHeight - this.dragHeight;
                            style.MarginTop = this._top + "px";
                            move_y = false;
                        }
                        if (vy > 0 && this._top > 0) {
                            this._top = this._posY = 0;
                            style.MarginTop = this._top + "px";
                            move_y = false;
                        }
                    }
                }

                //Note:Horizon
                if (move_x) {
                    vx += ax;
                    if (Math.Abs(vx) <= a) {
                        move_x = false;
                        this._posX = this._left;
                    } else {
                        this._left += (int)(vx * interval / 1000);
                        style.MarginLeft = this._left + "px";

                        if (vx < 0 && this.viewWidth - this._left > this.dragWidth) {
                            this._left = this._posX = this.viewWidth - this.dragWidth;
                            style.MarginLeft = this._left + "px";
                            move_x = false;
                        }
                        if (vx > 0 && this._left > 0) {
                            this._left = this._posX = 0;
                            style.MarginLeft = this._left + "px";
                            move_x = false;
                        }
                    }
                }

                if (!move_x && !move_y) {
                    System.Html.Window.ClearInterval(sid);
                }
            };
            var __m = _m.Bind(this);
            sid = System.Html.Window.SetInterval(__m, interval);
        }

        private void Dragging(Delta delta)
        {
            var style = this.__domNode.SearchByName("container").GetStyle();

            if (this.__allowHorizon)
            {
                if (this.dragWidth <= this.viewWidth)
                {
                    this._left = 0;
                }
                else if (delta.x > 0 && this._posX + delta.x > 0)
                {
                    //Note:Do nothing.
                }
                else if (delta.x < 0 && this._posX + delta.x + this.dragWidth < this.viewWidth)
                {
                    //Note:Do nothing.
                }
                else
                {
                    this._left = this._posX + delta.x;
                }
                style.MarginLeft = this._left + "px";
            }

            if (this.__allowVertical)
            {
                if (this.dragHeight <= this.viewHeight)
                {
                    this._top = 0;
                }
                else if (delta.y > 0 && this._posY + delta.y > 0)
                {
                    //Note:Do nothing.
                }
                else if (delta.y < 0 && this.viewHeight - (this._posY + delta.y) > this.dragHeight)
                {
                    //Note:Do nothing.
                }
                else
                {
                    this._top = this._posY + delta.y;
                }
                
                style.MarginTop = this._top + "px";
            }
        }
    }
}
